#include "RefractiveShader.h"


RefractiveShader::RefractiveShader(float _amount, vec4 _col, float _IOR):SurfaceShader(_amount){
	theColor = _col;
	indexOfRefraction = _IOR;
}


RefractiveShader::~RefractiveShader(){
}


vec4 RefractiveShader::getColor(Intersection &_int, Scene* _s){
	//check for max bounce depth
	if (_int.ray()->depth() == _int.ray()->maxDepth()){
		return vec4(0, 0, 0, 0);
	}

	Ray* theRay = _int.ray();
	float eta;
	int newType;
	vec3 newNorm = _int.surfNorm();
	//if the ray is  internal
	if (theRay->type() == 3){
		//IOR ratio is the index of refraction
		eta = indexOfRefraction;
		newNorm *= -1;	//flip the surface normal so the ray refracts out properly
	}
	else{
		//IOR ratio is 1 / index of refraction
		eta = 1.0f / indexOfRefraction;
	}
	//send a ray in the refraction direction
	vec3 pt = _int.getPos();
	vec3 refractDir = getRefractDir(theRay->direction(), newNorm, eta, newType);
	Ray *refractRay = new Ray(pt, refractDir, theRay->maxDepth(), theRay->depth() + 1, newType);
	Intersection _int2 = Intersection(refractRay);

	//get a pointer to the BVH
	BVH* _bvh = _s->theBVH();
	_bvh->intersect(_int2);

	if (!_int2.intersected()){
		return vec4(0, 0, 0, 0);
	}
	else{
		return _int2.shape()->getColor(_int2)/* * this->amount()*/;
	}

	
}

vec3 RefractiveShader::getRefractDir(vec3 _I, vec3 _N, float eta, int &_type){
	float nDOTi = dot(_N, _I);
	float k = 1.0f - eta * eta * (1.0f - nDOTi * nDOTi);
	if (k < 0){
		//internal reflection
		_type = 3;	//still transmission ray
		return _I - (2 * nDOTi * _N);
	}
	else{
		//refraction
		if (nDOTi < 0){
			_type = 3;
		}
		else{
			_type = 0;
		}
		return eta * _I - (eta * nDOTi + sqrtf(k)) * _N;
	}
}

vec4 RefractiveShader::color(){
	return theColor;
}
void RefractiveShader::color(vec4 _col){
	theColor = _col;
}

float RefractiveShader::IOR(){
	return indexOfRefraction;
}
void RefractiveShader::IOR(float _IOR){
	indexOfRefraction = _IOR;
}